/**
 * 210824：升级修改【three.js r120-r131】
 * 20220304:[require] to [import]...jordia
 */
import {Ray,Raycaster,Vector3,Matrix4} from 'three';
import DragLimit from "./drag-limit";
import Geometry from "../geometry-utils";


/**
 * 任意曲面（mesh）表面约束拖动
 */
export default class DragSurfaceLimit extends DragLimit{
    constructor(values){
        super(values);
    }

    /**
     * 获取约束类型
     * @returns {string}
     */
    get type(){
        return 'dragSurfaceLimit';
    }

    /**
     * 获取网格体
     * @returns {*|null|[*, *]}
     */
    get mesh(){
        return this._mesh;
    }

    /**
     * 设置网格体
     * @param mesh
     */
    set mesh(mesh){
        this._mesh=mesh;
    }

    modifyMove(object,v,callback,camera) {
        if(!this._mesh)return;
        camera.getWorldPosition(this._cameraPosition);
        this._tempDirection.subVectors(v, this._cameraPosition).normalize();
        this._raycaster.set(this._cameraPosition,this._tempDirection);
        let intersections=this._raycaster.intersectObject(this._mesh,false);
        if (intersections.length===0) {
            // this._tempInverse.getInverse(this._mesh.matrixWorld);20210824
            this._tempInverse.copy(this._mesh.matrixWorld).invert();
            v.applyMatrix4(this._tempInverse);
            this._cameraPosition.applyMatrix4(this._tempInverse);

            this._tempDir.subVectors(v, this._cameraPosition).normalize();
            this._tempRay.set(this._cameraPosition, this._tempDir);
            let closestPoint =new Vector3();
            Geometry.closestPointOfRayAndMesh(this._tempRay, this._mesh,closestPoint);
            closestPoint.applyMatrix4(this._mesh.matrixWorld);
            this._transformVector(object,closestPoint);
            object.position.copy(closestPoint);
            callback(object,closestPoint);
        }else {
            let closestPoint = intersections[0].point;
            this._transformVector(object,closestPoint);
            object.position.copy(closestPoint);
            callback(object, closestPoint);
        }
    }
    dispose(){
        super.dispose();
        this._mesh=null;
        this._cameraPosition=null;
        this._tempDirection=null;
        this._tempRay=null;
        this._raycaster=null;
        this._tempInverse=null;
        this._tempDir=null;
    }

    _initVariable() {
        super._initVariable();
        this._mesh=null;

        this._cameraPosition=new Vector3();
        this._tempDirection=new Vector3();
        this._tempRay=new Ray();
        this._raycaster=new Raycaster();
        this._tempInverse=new Matrix4();
        this._tempDir=new Vector3();
    }
}